minAngle = strtod(minangleopt, nullptr);
}
- route_backup(&routes_orig_num, &routes_orig);
+ route_backup(&routes_orig);
route_flush_all_routes();
}
void BendFilter::process()
{
- queue* elem, *tmp;
- QUEUE_FOR_EACH(routes_orig, elem, tmp) {
- route_head* route_orig = reinterpret_cast<route_head *>(elem);
+ for (auto it = routes_orig->cbegin(); it != routes_orig->cend(); ++it) {
+ auto route_orig = reinterpret_cast<const route_head*>(*it);
process_route_orig(route_orig);
}
}
void BendFilter::deinit()
{
- route_flush(routes_orig);
- xfree(routes_orig);
+ routes_orig->flush();
+ delete routes_orig;
+ routes_orig = nullptr;
}
#endif // FILTERS_ENABLED
double maxDist;
double minAngle;
- queue* routes_orig = nullptr;
- int routes_orig_num = 0;
+ RouteList* routes_orig = nullptr;
arglist_t args[3] = {
{
#else
queue* elem, *tmp;
QUEUE_FOR_EACH(&waypt_head, elem, tmp) {
- Waypoint* waypointp = reinterpret_cast<Waypoint *>(elem);
+ Waypoint* waypointp = reinterpret_cast<Waypoint*>(elem);
#endif
if ((se == nullptr) || (waypointp->session == se)) {
if (global_opts.verbose_status) {
public:
route_head();
+ // the default copy constructor and assignment operator are not appropriate as we do deep copy of some members,
+ // and we haven't bothered to write an appropriate one.
+ // Catch attempts to use the default copy constructor and assignment operator.
+ route_head(const route_head& other) = delete;
+ route_head& operator=(const route_head& rhs) = delete;
~route_head();
};
typedef void (*route_hdr)(const route_head*);
typedef void (*route_trl)(const route_head*);
+// TODO: Consider using composition instead of private inheritance.
+class RouteList : private QueueList<queue>
+{
+public:
+// FIXME: The interface should NOT depend on the implementation of the list.
+// Migrate to std::sort using a compare function
+// typedef bool (*Compare)(const route_head* a, const route_head* b);
+ typedef int (*Compare)(const queue* a, const queue* b);
+
+ RouteList();
+
+ int count() const; // a.k.a. size()
+ int waypt_count() const;
+ void add_head(route_head* rte); // a.k.a. append(), push_back()
+ // FIXME: Generally it is inefficient to use an element pointer or reference to define the element to be deleted, use iterator instead,
+ // and/or implement pop_back() a.k.a. removeLast(), and/or pop_front() a.k.a. removeFirst().
+ void del_head(route_head* rte); // a.k.a. erase()
+ // FIXME: Generally it is inefficent to use an element pointer or reference to define the insertion point, use iterator instead.
+ void insert_head(route_head* rte, route_head* predecessor); // a.k.a. insert
+ void add_wpt(route_head* rte, Waypoint* wpt, bool synth, const QString& namepart, int number_digits);
+ // FIXME: Generally it is inefficent to use an element pointer or reference to define the insertion point, use iterator instead.
+ void del_wpt(route_head* rte, Waypoint* wpt);
+ void common_disp_session(const session_t* se, route_hdr rh, route_trl rt, waypt_cb wc);
+ void flush(); // a.k.a. clear()
+ void copy(RouteList** dst) const;
+ void restore(RouteList* src);
+ void swap(RouteList& other);
+ void sort(Compare cmp);
+ template <typename T1, typename T2, typename T3>
+ void disp_all(T1 rh, T2 rt, T3 wc);
+ template <typename T2, typename T3>
+ void disp_all(std::nullptr_t /* rh */, T2 rt, T3 wc);
+ template <typename T1, typename T3>
+ void disp_all(T1 rh, std::nullptr_t /* rt */, T3 wc);
+ template <typename T3>
+ void disp_all(std::nullptr_t /* rh */, std::nullptr_t /* rt */, T3 wc);
+
+ // Only expose methods from our underlying container that won't corrupt our private data.
+ // Our contained element (route_head) also contains a container (waypoint_list),
+ // and we maintain a total count the elements in these contained containers, i.e.
+ // the total number of waypoints in all the routes in the RouteList.
+ using QueueList<queue>::begin;
+ using QueueList<queue>::end;
+ using QueueList<queue>::cbegin;
+ using QueueList<queue>::cend;
+ using QueueList<queue>::empty; // a.k.a. isEmpty()
+ using QueueList<queue>::front; // a.k.a. first()
+ using QueueList<queue>::back; // a.k.a. last()
+ using QueueList<queue>::Iterator;
+ using QueueList<queue>::ConstIterator;
+
+private:
+ queue head;
+ int head_ct{0};
+ int waypt_ct{0};
+};
+
void route_init();
unsigned int route_waypt_count();
unsigned int route_count();
void track_add_head(route_head* rte);
void track_del_head(route_head* rte);
void track_insert_head(route_head* rte, route_head* predecessor);
-route_head* route_find_route_by_name(const char* name);
-route_head* route_find_track_by_name(const char* name);
-void route_add_wpt_named(route_head* rte, Waypoint* wpt, const QString& namepart, int number_digits);
-void route_add_wpt(route_head* rte, Waypoint* wpt);
-void track_add_wpt_named(route_head* rte, Waypoint* wpt, const QString& namepart, int number_digits);
-void track_add_wpt(route_head* rte, Waypoint* wpt);
-Waypoint* route_find_waypt_by_name(route_head* rh, const char* name);
+void route_add_wpt(route_head* rte, Waypoint* wpt, const QString& namepart = "RPT", int number_digits = 3);
+void track_add_wpt(route_head* rte, Waypoint* wpt, const QString& namepart = "RPT", int number_digits = 3);
void route_del_wpt(route_head* rte, Waypoint* wpt);
void track_del_wpt(route_head* rte, Waypoint* wpt);
//void route_disp(const route_head* rte, waypt_cb); /* template */
void track_disp_session(const session_t* se, route_hdr rh, route_trl rt, waypt_cb wc);
void route_flush_all_routes();
void route_flush_all_tracks();
-void route_flush_all();
-void route_flush(queue* head);
-void route_copy(int* dst_count, int* dst_wpt_count, queue** dst, queue* src);
-void route_append(queue* src);
-void track_append(queue* src);
-void route_backup(signed int* count, queue** head_bak);
-void route_restore(queue* head_bak);
-void track_backup(signed int* count, queue** head_bak);
-void track_restore(queue* head_bak);
+void route_deinit();
+void route_append(RouteList* src);
+void track_append(RouteList* src);
+void route_backup(RouteList** head_bak);
+void route_restore(RouteList* head_bak);
+void route_swap(RouteList& other);
+void route_sort(RouteList::Compare cmp);
+void track_backup(RouteList** head_bak);
+void track_restore(RouteList* head_bak);
+void track_swap(RouteList& other);
+void track_sort(RouteList::Compare cmp);
computed_trkdata track_recompute(const route_head* trk);
template <typename T>
// cb != nullptr, caught with an overload of route_disp
QUEUE_FOR_EACH(&rh->waypoint_list, elem, tmp) {
Waypoint* waypointp;
- waypointp = reinterpret_cast<Waypoint *>(elem);
+ waypointp = reinterpret_cast<Waypoint*>(elem);
cb(waypointp);
}
}
template <typename T1, typename T2, typename T3>
void
-common_disp_all(queue* qh, T1 rh, T2 rt, T3 wc)
+RouteList::disp_all(T1 rh, T2 rt, T3 wc)
{
queue* elem, *tmp;
- QUEUE_FOR_EACH(qh, elem, tmp) {
+ QUEUE_FOR_EACH(&head, elem, tmp) {
const route_head* rhp;
- rhp = reinterpret_cast<route_head *>(elem);
+ rhp = reinterpret_cast<route_head*>(elem);
// rh != nullptr, caught with an overload of common_disp_all
rh(rhp);
route_disp(rhp, wc);
template <typename T2, typename T3>
void
-common_disp_all(queue* qh, std::nullptr_t /* rh */, T2 rt, T3 wc)
+RouteList::disp_all(std::nullptr_t /* rh */, T2 rt, T3 wc)
{
queue* elem, *tmp;
- QUEUE_FOR_EACH(qh, elem, tmp) {
+ QUEUE_FOR_EACH(&head, elem, tmp) {
const route_head* rhp;
- rhp = reinterpret_cast<route_head *>(elem);
+ rhp = reinterpret_cast<route_head*>(elem);
// rh == nullptr
route_disp(rhp, wc);
// rt != nullptr, caught with an overload of common_disp_all
template <typename T1, typename T3>
void
-common_disp_all(queue* qh, T1 rh, std::nullptr_t /* rt */, T3 wc)
+RouteList::disp_all(T1 rh, std::nullptr_t /* rt */, T3 wc)
{
queue* elem, *tmp;
- QUEUE_FOR_EACH(qh, elem, tmp) {
+ QUEUE_FOR_EACH(&head, elem, tmp) {
const route_head* rhp;
- rhp = reinterpret_cast<route_head *>(elem);
+ rhp = reinterpret_cast<route_head*>(elem);
// rh != nullptr, caught with an overload of common_disp_all
rh(rhp);
route_disp(rhp, wc);
template <typename T3>
void
-common_disp_all(queue* qh, std::nullptr_t /* rh */, std::nullptr_t /* rt */, T3 wc)
+RouteList::disp_all(std::nullptr_t /* rh */, std::nullptr_t /* rt */, T3 wc)
{
queue* elem, *tmp;
- QUEUE_FOR_EACH(qh, elem, tmp) {
+ QUEUE_FOR_EACH(&head, elem, tmp) {
const route_head* rhp;
- rhp = reinterpret_cast<route_head *>(elem);
+ rhp = reinterpret_cast<route_head*>(elem);
// rh == nullptr
route_disp(rhp, wc);
// rt == nullptr
void
route_disp_all(T1 rh, T2 rt, T3 wc)
{
- extern queue my_route_head;
+ extern RouteList* global_route_list;
- common_disp_all(&my_route_head, rh, rt, wc);
+ global_route_list->disp_all(rh, rt, wc);
}
template <typename T1, typename T2, typename T3>
void
track_disp_all(T1 rh, T2 rt, T3 wc)
{
- extern queue my_track_head;
+ extern RouteList* global_track_list;
- common_disp_all(&my_track_head, rh, rt, wc);
+ global_track_list->disp_all(rh, rt, wc);
}
typedef struct {
/*
* From nmea.c
*/
-int nmea_cksum(const char*buf);
+int nmea_cksum(const char* buf);
/*
* Color helpers.
void InterpolateFilter::process()
{
- queue* backuproute = nullptr;
- queue* elem, *tmp, *elem2, *tmp2;
- int count = 0;
+ RouteList* backuproute = nullptr;
+ queue* elem2, *tmp2;
double lat1 = 0, lon1 = 0;
double altitude1 = unknown_alt;
unsigned int time1 = 0;
double frac;
if (opt_route) {
- route_backup(&count, &backuproute);
+ route_backup(&backuproute);
route_flush_all_routes();
} else {
- track_backup(&count, &backuproute);
+ track_backup(&backuproute);
route_flush_all_tracks();
}
- if (count == 0) {
+ if (backuproute->empty()) {
fatal(MYNAME ": Found no routes or tracks to operate on.\n");
}
- QUEUE_FOR_EACH(backuproute, elem, tmp) {
- route_head* rte_old = reinterpret_cast<route_head *>(elem);
+ for (auto it = backuproute->cbegin(); it != backuproute->cend(); ++it) {
+ auto rte_old = reinterpret_cast<const route_head*>(*it);
route_head* rte_new = route_head_alloc();
rte_new->rte_name = rte_old->rte_name;
time1 = wpt->creation_time.toTime_t();
}
}
- route_flush(backuproute);
- xfree(backuproute);
+ backuproute->flush();
+ delete backuproute;
}
void InterpolateFilter::init()
int opt_version = 0;
int did_something = 0;
const char* prog_name = argv[0]; /* argv is modified during processing */
- queue* wpt_head_bak, *rte_head_bak, *trk_head_bak; /* #ifdef UTF8_SUPPORT */
- signed int wpt_ct_bak, rte_ct_bak, trk_ct_bak; /* #ifdef UTF8_SUPPORT */
+ queue* wpt_head_bak; /* #ifdef UTF8_SUPPORT */
+ RouteList* rte_head_bak, *trk_head_bak; /* #ifdef UTF8_SUPPORT */
+ signed int wpt_ct_bak; /* #ifdef UTF8_SUPPORT */
+ bool lists_backedup; /* #ifdef UTF8_SUPPORT */
QStack<QargStackElement> qargs_stack = QStack<QargStackElement>();
// Create a QCoreApplication object to handle application initialization.
cet_convert_init(ovecs->encode, ovecs->fixed_encode);
- wpt_ct_bak = -1;
- rte_ct_bak = -1;
- trk_ct_bak = -1;
+ lists_backedup = false;
rte_head_bak = trk_head_bak = nullptr;
ovecs->wr_init(ofname);
*/
int saved_status = global_opts.verbose_status;
global_opts.verbose_status = 0;
+ lists_backedup = true;
waypt_backup(&wpt_ct_bak, &wpt_head_bak);
- route_backup(&rte_ct_bak, &rte_head_bak);
- track_backup(&trk_ct_bak, &trk_head_bak);
+ route_backup(&rte_head_bak);
+ track_backup(&trk_head_bak);
cet_convert_strings(nullptr, global_opts.charset, nullptr);
global_opts.verbose_status = saved_status;
cet_convert_deinit();
- if (wpt_ct_bak != -1) {
+ if (lists_backedup) {
waypt_restore(wpt_ct_bak, wpt_head_bak);
- }
- if (rte_ct_bak != -1) {
route_restore(rte_head_bak);
- xfree(rte_head_bak);
- }
- if (trk_ct_bak != -1) {
+ delete rte_head_bak;
track_restore(trk_head_bak);
- xfree(trk_head_bak);
+ delete trk_head_bak;
}
}
break;
cet_deregister();
waypt_flush_all();
- route_flush_all();
+ route_deinit();
session_exit();
exit_vecs();
exit_filter_vecs();
#ifndef QUEUE_H_INCLUDED_
#define QUEUE_H_INCLUDED_
+#include <iterator>
+
typedef struct queue {
struct queue* next;
struct queue* prev;
(element) != (listhead); \
(element) = (tmp))
+// FIXME: g++ 7.3.0, -O2, with T=route_head yields warnings.
+// implementing QueueList as a template was meant to
+// i) avoid reinterpret_casts all over the code as with QUEUE_FOR_EACH
+// ii) allow use of range based for loops.
+// If this isn't fixed then QueueList doesn't need to be a template, T == queue.
+// In file included from defs.h:27:0,
+// from bend.cc:23:
+// queue.h: In instantiation of ‘const T*& QueueList<T>::ConstIterator::operator*() [with T = route_head; QueueList<T>::ConstIterator::reference = const route_head*&]’:
+// bend.cc:162:24: required from here
+// queue.h:143:14: warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]
+// return reinterpret_cast<reference>(ptr_);
+// ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+template <typename T>
+class QueueList
+{
+public:
+
+ QueueList(queue* head, int* ct) : head_{head}, ct_{ct} {}
+
+ class Iterator
+ {
+ public:
+ using iterator_category = std::bidirectional_iterator_tag;
+ using value_type = T*;
+ using difference_type = std::ptrdiff_t;
+ using pointer = T** ;
+ using reference = T* &;
+
+ Iterator() = default;
+ explicit Iterator(queue* p) : ptr_{p} {}
+
+ reference operator*()
+ {
+ return reinterpret_cast<reference>(ptr_);
+ }
+ pointer operator->()
+ {
+ return reinterpret_cast<pointer>(&ptr_);
+ }
+ Iterator& operator++() // pre-increment
+ {
+ ptr_ = ptr_->next;
+ return *this;
+ }
+ Iterator operator++(int) // post-increment
+ {
+ Iterator tmp = *this;
+ ++*this;
+ return tmp;
+ }
+ Iterator& operator--() // pre-decrement
+ {
+ ptr_ = ptr_->prev;
+ return *this;
+ }
+ Iterator operator--(int) // post-decrement
+ {
+ Iterator tmp = *this;
+ --*this;
+ return tmp;
+ }
+ bool operator==(const Iterator& other) const
+ {
+ return ptr_ == other.ptr_;
+ }
+ bool operator!=(const Iterator& other) const
+ {
+ return ptr_ != other.ptr_;
+ }
+
+ private:
+ queue* ptr_{nullptr};
+ };
+ //friend class Iterator;
+
+ class ConstIterator
+ {
+ public:
+ using iterator_category = std::bidirectional_iterator_tag;
+ using value_type = T*;
+ using difference_type = std::ptrdiff_t;
+ using pointer = const T** ;
+ using reference = const T* &;
+
+ ConstIterator() = default;
+ explicit ConstIterator(const queue* p) : ptr_{p} {}
+
+ reference operator*()
+ {
+ return reinterpret_cast<reference>(ptr_);
+ }
+ pointer operator->()
+ {
+ return reinterpret_cast<pointer>(&ptr_);
+ }
+ ConstIterator& operator++() // pre-increment
+ {
+ ptr_ = ptr_->next;
+ return *this;
+ }
+ ConstIterator operator++(int) // post-increment
+ {
+ ConstIterator tmp = *this;
+ ++*this;
+ return tmp;
+ }
+ ConstIterator& operator--() // pre-decrement
+ {
+ ptr_ = ptr_->prev;
+ return *this;
+ }
+ ConstIterator operator--(int) // post-decrement
+ {
+ ConstIterator tmp = *this;
+ --*this;
+ return tmp;
+ }
+ bool operator==(const ConstIterator& other) const
+ {
+ return ptr_ == other.ptr_;
+ }
+ bool operator!=(const ConstIterator& other) const
+ {
+ return ptr_ != other.ptr_;
+ }
+
+ private:
+ const queue* ptr_{nullptr};
+ };
+ //friend class ConstIterator;
+
+ Iterator begin()
+ {
+ return Iterator(head_->next);
+ }
+ ConstIterator begin() const
+ {
+ return ConstIterator(head_->next);
+ }
+ Iterator end()
+ {
+ return Iterator(head_);
+ }
+ ConstIterator end() const
+ {
+ return ConstIterator(head_);
+ }
+ ConstIterator cbegin()
+ {
+ return ConstIterator(head_->next);
+ }
+ ConstIterator cend()
+ {
+ return ConstIterator(head_);
+ }
+
+ bool empty() const
+ {
+ return begin() == end();
+ }
+
+ T& front()
+ {
+ return reinterpret_cast<T&>(**begin());
+ }
+
+ const T& front() const
+ {
+ return reinterpret_cast<const T&>(**begin());
+ }
+
+ T& back()
+ {
+ auto tmp = end();
+ --tmp;
+ return reinterpret_cast<T&>(**tmp);
+ }
+
+ const T& back() const
+ {
+ auto tmp = end();
+ --tmp;
+ return reinterpret_cast<const T&>(**tmp);
+ }
+
+private:
+ queue* head_;
+ int* ct_;
+};
+
+
/*
* The following sorting code was derived from linked-list mergesort
* sample code by Simon Tatham, code obtained from:
*/
#include "defs.h"
-#include "grtcirc.h"
-#include "session.h"
-#include <cstdio>
-
-queue my_route_head;
-queue my_track_head;
-static int rte_head_ct;
-static int rte_waypts;
-static int trk_head_ct;
-static int trk_waypts;
+#include "grtcirc.h" // for RAD, gcdist, heading_true_degrees, radtometers
+#include "queue.h" // for queue, dequeue, QUEUE_FOR_EACH, QUEUE_MOVE, QUEUE_INIT, sortqueue, ENQUEUE_TAIL, QUEUE_EMPTY, ENQUEUE_AFTER, ENQUEUE_HEAD, QUEUE_LAST, QUEUE_NEXT, QueueList
+#include "session.h" // for curr_session, session_t (ptr only)
+#include "src/core/datetime.h" // for DateTime
+#include "src/core/optional.h" // for optional, operator>, operator<
+#include <QtCore/QDateTime> // for QDateTime
+#include <QtCore/QString> // for QString
+#include <cstddef> // for nullptr_t
+
+RouteList* global_route_list;
+RouteList* global_track_list;
extern void update_common_traits(const Waypoint* wpt);
void
route_init()
{
- QUEUE_INIT(&my_route_head);
- QUEUE_INIT(&my_track_head);
+ global_route_list = new RouteList;
+ global_track_list = new RouteList;
}
unsigned int
route_waypt_count()
{
- /* total wapoint count -- all routes */
- return rte_waypts;
+ /* total waypoint count -- all routes */
+ return global_route_list->waypt_count();
}
unsigned int
route_count()
{
- return rte_head_ct; /* total # of routes */
+ return global_route_list->count(); /* total # of routes */
}
unsigned int
track_waypt_count()
{
- /* totaly waypoint count -- all tracks */
- return trk_waypts;
+ /* total waypoint count -- all tracks */
+ return global_track_list->waypt_count();
}
unsigned int
track_count()
{
- return trk_head_ct; /* total # of tracks */
+ return global_track_list->count(); /* total # of tracks */
}
+// FIXME: provide a method to deallocate a head that isn't added onto a route list,
+// or just let the users allocate with new and deallocate with delete.
route_head*
route_head_alloc()
{
- route_head* rte_head = new route_head;
- return rte_head;
-}
-
-static void
-any_route_free(route_head* rte)
-{
- delete rte;
- rte = nullptr;
-}
-
-static void
-any_route_add_head(route_head* rte, queue* head)
-{
- ENQUEUE_TAIL(head, &rte->Q);
-}
-
-static void
-any_route_del_head(route_head* rte)
-{
- dequeue(&rte->Q);
- any_route_free(rte);
+ return new route_head;
}
void
route_add_head(route_head* rte)
{
- any_route_add_head(rte, &my_route_head);
- rte_head_ct++;
+ global_route_list->add_head(rte);
}
void
route_del_head(route_head* rte)
{
- rte_waypts -= rte->rte_waypt_ct;
- any_route_del_head(rte);
- rte_head_ct--;
+ global_route_list->del_head(rte);
}
void
track_add_head(route_head* rte)
{
- any_route_add_head(rte, &my_track_head);
- trk_head_ct++;
+ global_track_list->add_head(rte);
}
void
track_del_head(route_head* rte)
{
- trk_waypts -= rte->rte_waypt_ct;
- any_route_del_head(rte);
- trk_head_ct--;
+ global_track_list->del_head(rte);
}
void
track_insert_head(route_head* rte, route_head* predecessor)
{
- ENQUEUE_AFTER(&predecessor->Q, &rte->Q);
- trk_head_ct++;
+ global_track_list->insert_head(rte, predecessor);
}
+// FIXME: can we delete this unused and untested code?
+#ifdef DEAD_CODE_IS_REBORN
static
route_head*
common_route_by_name(queue* routes, const char* name)
queue* elem, *tmp;
QUEUE_FOR_EACH(routes, elem, tmp) {
- route_head* rte = reinterpret_cast<route_head *>(elem);
+ route_head* rte = reinterpret_cast<route_head*>(elem);
if (rte->rte_name == name) {
return rte;
}
{
return common_route_by_name(&my_track_head, name);
}
-
-static void
-any_route_add_wpt(route_head* rte, Waypoint* wpt, int* ct, int synth, const QString& namepart, int number_digits)
-{
- ENQUEUE_TAIL(&rte->waypoint_list, &wpt->Q);
- rte->rte_waypt_ct++; /* waypoints in this route */
- if (ct) {
- (*ct)++;
- }
- if (synth && wpt->shortname.isEmpty()) {
- wpt->shortname = QString().sprintf("%s%0*d", CSTRc(namepart), number_digits, *ct);
- wpt->wpt_flags.shortname_is_synthetic = 1;
- }
- update_common_traits(wpt);
-}
+#endif
void
-route_add_wpt_named(route_head* rte, Waypoint* wpt, const QString& namepart, int number_digits)
+route_add_wpt(route_head* rte, Waypoint* wpt, const QString& namepart, int number_digits)
{
// First point in a route is always a new segment.
// This improves compatibility when reading from
wpt->wpt_flags.new_trkseg = 1;
}
- any_route_add_wpt(rte, wpt, &rte_waypts, 1, namepart, number_digits);
+ global_route_list->add_wpt(rte, wpt, true, namepart, number_digits);
}
void
-route_add_wpt(route_head* rte, Waypoint* wpt)
-{
- const char RPT[] = "RPT";
- route_add_wpt_named(rte, wpt, RPT, 3);
-}
-
-void
-track_add_wpt_named(route_head* rte, Waypoint* wpt, const QString& namepart, int number_digits)
+track_add_wpt(route_head* rte, Waypoint* wpt, const QString& namepart, int number_digits)
{
// First point in a track is always a new segment.
// This improves compatibility when reading from
wpt->wpt_flags.new_trkseg = 1;
}
- any_route_add_wpt(rte, wpt, &trk_waypts, 0, namepart, number_digits);
-}
-
-void
-track_add_wpt(route_head* rte, Waypoint* wpt)
-{
- const char RPT[] = "RPT";
- track_add_wpt_named(rte, wpt, RPT, 3);
+ // FIXME: It is misleading to accept namepart and number_digits parameters which
+ // are ignored because synth is set to false.
+ global_track_list->add_wpt(rte, wpt, false, namepart, number_digits);
}
+// FIXME: can we delete this unused and untested code?
+#ifdef DEAD_CODE_IS_REBORN
Waypoint*
route_find_waypt_by_name(route_head* rh, const char* name)
{
queue* elem, *tmp;
QUEUE_FOR_EACH(&rh->waypoint_list, elem, tmp) {
- Waypoint* waypointp = reinterpret_cast<Waypoint *>(elem);
+ Waypoint* waypointp = reinterpret_cast<Waypoint*>(elem);
if (waypointp->shortname == name) {
return waypointp;
}
}
return nullptr;
}
-
-static void
-any_route_del_wpt(route_head* rte, Waypoint* wpt, int* ct)
-{
- if (wpt->wpt_flags.new_trkseg && wpt != reinterpret_cast<Waypoint *>QUEUE_LAST(&rte->waypoint_list)) {
- Waypoint* wpt_next = reinterpret_cast<Waypoint *>QUEUE_NEXT(&wpt->Q);
- wpt_next->wpt_flags.new_trkseg = 1;
- }
- wpt->wpt_flags.new_trkseg = 0;
- dequeue(&wpt->Q);
- rte->rte_waypt_ct--;
- if (ct) {
- (*ct)--;
- }
-}
+#endif
void
route_del_wpt(route_head* rte, Waypoint* wpt)
{
- any_route_del_wpt(rte, wpt, &rte_waypts);
+ global_route_list->del_wpt(rte, wpt);
}
void
track_del_wpt(route_head* rte, Waypoint* wpt)
{
- any_route_del_wpt(rte, wpt, &trk_waypts);
+ global_track_list->del_wpt(rte, wpt);
}
void
route_reverse(const route_head* rte_hd)
{
/* Cast away const-ness */
- route_head* rh = const_cast<route_head*>(rte_hd);
+ auto rh = const_cast<route_head*>(rte_hd);
queue* elem, *tmp;
QUEUE_FOR_EACH(&rh->waypoint_list, elem, tmp) {
ENQUEUE_HEAD(&rh->waypoint_list, dequeue(elem));
}
}
-static void
-common_disp_session(const session_t* se, queue* qh, route_hdr rh, route_trl rt, waypt_cb wc)
-{
- queue* elem, *tmp;
- QUEUE_FOR_EACH(qh, elem, tmp) {
- const route_head* rhp = reinterpret_cast<route_head *>(elem);
- if (rhp->session == se) {
- if (rh) {
- (*rh)(rhp);
- }
- route_disp(rhp, wc);
- if (rt) {
- (*rt)(rhp);
- }
- }
- }
-}
-
void
route_disp_session(const session_t* se, route_hdr rh, route_trl rt, waypt_cb wc)
{
- common_disp_session(se, &my_route_head, rh, rt, wc);
+ global_route_list->common_disp_session(se, rh, rt, wc);
}
void
track_disp_session(const session_t* se, route_hdr rh, route_trl rt, waypt_cb wc)
{
- common_disp_session(se, &my_track_head, rh, rt, wc);
-}
-
-static void
-route_flush_q(queue* head)
-{
- queue* elem, *tmp;
-
- QUEUE_FOR_EACH(head, elem, tmp) {
- queue* q = dequeue(elem);
- any_route_free(reinterpret_cast<route_head *>(q));
- }
+ global_track_list->common_disp_session(se, rh, rt, wc);
}
void
route_flush_all_routes()
{
- route_flush_q(&my_route_head);
- rte_head_ct = 0;
- rte_waypts = 0;
+ global_route_list->flush();
}
void
route_flush_all_tracks()
{
- route_flush_q(&my_track_head);
- trk_head_ct = 0;
- trk_waypts = 0;
+ global_track_list->flush();
}
void
-route_flush_all()
+route_deinit()
{
- route_flush_all_tracks();
route_flush_all_routes();
+ route_flush_all_tracks();
+ delete global_route_list;
+ delete global_track_list;
}
void
-route_flush(queue* head)
+route_append(RouteList* src)
{
- queue* elem, *tmp;
- QUEUE_FOR_EACH(head, elem, tmp) {
- queue* q = dequeue(elem);
- any_route_free(reinterpret_cast<route_head *>(q));
- }
+ src->copy(&global_route_list);
}
void
-route_copy(int* dst_count, int* dst_wpt_count, queue** dst, queue* src)
+track_append(RouteList* src)
{
- queue* elem, *tmp, *elem2, *tmp2;
- int junk;
- if (!dst_wpt_count) {
- dst_wpt_count = &junk;
- }
-
- if (!*dst) {
- *dst = (queue*)xcalloc(1, sizeof(queue));
- QUEUE_INIT(*dst);
- *dst_count = 0;
- *dst_wpt_count = 0;
- }
-
- const char RPT[] = "RPT";
- QUEUE_FOR_EACH(src, elem, tmp) {
- route_head* rte_old = reinterpret_cast<route_head *>(elem);
-
- route_head* rte_new = route_head_alloc();
- rte_new->rte_name = rte_old->rte_name;
- rte_new->rte_desc = rte_old->rte_desc;
- rte_new->rte_urls = rte_old->rte_urls;
- rte_new->fs = fs_chain_copy(rte_old->fs);
- rte_new->rte_num = rte_old->rte_num;
- any_route_add_head(rte_new, *dst);
- QUEUE_FOR_EACH(&rte_old->waypoint_list, elem2, tmp2) {
- any_route_add_wpt(rte_new, new Waypoint(*reinterpret_cast<Waypoint *>(elem2)), dst_wpt_count, 0, RPT, 3);
- }
- (*dst_count)++;
- }
+ src->copy(&global_track_list);
}
void
-route_append(queue* src)
+route_backup(RouteList** head_bak)
{
- queue* dst = &my_route_head;
- route_copy(&rte_head_ct, &rte_waypts, &dst, src);
+ global_route_list->copy(head_bak);
}
void
-track_append(queue* src)
+route_restore(RouteList* head_bak)
{
- queue* dst = &my_track_head;
- route_copy(&trk_head_ct, &trk_waypts, &dst, src);
+ global_route_list->restore(head_bak);
}
void
-route_backup(signed int* count, queue** head_bak)
-{
- route_copy(count, nullptr, head_bak, &my_route_head);
-}
-
-static void
-route_restore_hdr(const route_head* rte)
-{
- (void)rte;
- rte_head_ct++;
-}
-
-static void
-track_restore_hdr(const route_head* trk)
-{
- (void)trk;
- trk_head_ct++;
-}
-
-static void
-route_restore_tlr(const route_head* rte)
-{
- (void)rte;
-}
-
-static void
-route_restore_wpt(const Waypoint* wpt)
+route_swap(RouteList& other)
{
- (void)wpt;
- rte_waypts++;
+ global_route_list->swap(other);
}
-static void
-track_restore_wpt(const Waypoint* wpt)
+void
+route_sort(RouteList::Compare cmp)
{
- (void)wpt;
- trk_waypts++;
+ global_route_list->sort(cmp);
}
-static void
-common_restore_finish()
+void
+track_backup(RouteList** head_bak)
{
- rte_head_ct = 0;
- trk_head_ct = 0;
- rte_waypts = 0;
- trk_waypts = 0;
- route_disp_all(route_restore_hdr, route_restore_tlr, route_restore_wpt);
- track_disp_all(track_restore_hdr, route_restore_tlr, track_restore_wpt);
+ global_track_list->copy(head_bak);
}
void
-route_restore(queue* head_bak)
+track_restore(RouteList* head_bak)
{
- if (head_bak == nullptr) {
- return;
- }
-
- route_flush_q(&my_route_head);
- QUEUE_INIT(&my_route_head);
- QUEUE_MOVE(&my_route_head, head_bak);
-
- common_restore_finish();
+ global_track_list->restore(head_bak);
}
void
-track_backup(signed int* count, queue** head_bak)
+track_swap(RouteList& other)
{
- route_copy(count, nullptr, head_bak, &my_track_head);
+ global_track_list->swap(other);
}
void
-track_restore(queue* head_bak)
+track_sort(RouteList::Compare cmp)
{
- if (head_bak == nullptr) {
- return;
- }
-
- route_flush_q(&my_track_head);
- QUEUE_INIT(&my_track_head);
- QUEUE_MOVE(&my_track_head, head_bak);
-
- common_restore_finish();
+ global_track_list->sort(cmp);
}
+// FIXME: can we delete this unused and untested code?
#ifdef DEAD_CODE_IS_REBORN
/*
* Move the entire track queue onto the route queue making no attempt
}
#endif
+// FIXME: can we delete this unused and untested code?
#ifdef DEAD_CODE_IS_REBORN
/*
* Same, but in opposite direction.
// first.longitude = 0;
// first.creation_time = 0;
- QUEUE_FOR_EACH((queue*)&trk->waypoint_list, elem, tmp) {
- Waypoint* thisw = reinterpret_cast<Waypoint *>(elem);
+ QUEUE_FOR_EACH(&trk->waypoint_list, elem, tmp) {
+ auto thisw = reinterpret_cast<Waypoint*>(elem);
/*
* gcdist and heading want radians, not degrees.
fs_chain_destroy(fs);
}
}
+
+RouteList::RouteList() : QueueList<queue>(&head, &head_ct)
+{
+ QUEUE_INIT(&head);
+}
+
+int RouteList::count() const
+{
+ return head_ct;
+}
+
+int RouteList::waypt_count() const
+{
+ return waypt_ct;
+}
+
+// rte may or may not contain waypoints in it's waypoint_list.
+// FIXME: In the case that it does, our count of total waypoints won't
+// match until after rte is added.
+// examples are in tests for garmin_txt, gdb, ggv_log, ik3d, navitel, osm.
+void
+RouteList::add_head(route_head* rte)
+{
+ ENQUEUE_TAIL(&head, &rte->Q);
+ ++head_ct;
+}
+
+void
+RouteList::del_head(route_head* rte)
+{
+ waypt_ct -= rte->rte_waypt_ct;
+ dequeue(&rte->Q);
+ delete rte;
+ --head_ct;
+}
+
+void
+RouteList::insert_head(route_head* rte, route_head* predecessor)
+{
+ ENQUEUE_AFTER(&predecessor->Q, &rte->Q);
+ ++head_ct;
+}
+
+// Synthesizing names based on the total number of waypoints in the RouteList makes
+// it advantageous to keep a count of the total number of waypoints in all the routes
+// in the RouteList AND any routes that have had waypoints added but haven't been
+// added themselves yet.
+void
+RouteList::add_wpt(route_head* rte, Waypoint* wpt, bool synth, const QString& namepart, int number_digits)
+{
+ ENQUEUE_TAIL(&rte->waypoint_list, &wpt->Q);
+ rte->rte_waypt_ct++; /* waypoints in this route */
+ ++waypt_ct;
+ if (synth && wpt->shortname.isEmpty()) {
+ wpt->shortname = QString().sprintf("%s%0*d", CSTRc(namepart), number_digits, waypt_ct);
+ wpt->wpt_flags.shortname_is_synthetic = 1;
+ }
+ update_common_traits(wpt);
+}
+
+void
+RouteList::del_wpt(route_head* rte, Waypoint* wpt)
+{
+ if (wpt->wpt_flags.new_trkseg && wpt != reinterpret_cast<Waypoint*>QUEUE_LAST(&rte->waypoint_list)) {
+ auto wpt_next = reinterpret_cast<Waypoint*>QUEUE_NEXT(&wpt->Q);
+ wpt_next->wpt_flags.new_trkseg = 1;
+ }
+ wpt->wpt_flags.new_trkseg = 0;
+ dequeue(&wpt->Q);
+ rte->rte_waypt_ct--;
+ --waypt_ct;
+}
+
+void
+RouteList::common_disp_session(const session_t* se, route_hdr rh, route_trl rt, waypt_cb wc)
+{
+ queue* elem, *tmp;
+ QUEUE_FOR_EACH(&head, elem, tmp) {
+ const route_head* rhp = reinterpret_cast<route_head*>(elem);
+ if (rhp->session == se) {
+ if (rh) {
+ (*rh)(rhp);
+ }
+ route_disp(rhp, wc);
+ if (rt) {
+ (*rt)(rhp);
+ }
+ }
+ }
+}
+
+void
+RouteList::flush()
+{
+ queue* elem, *tmp;
+
+ QUEUE_FOR_EACH(&head, elem, tmp) {
+ queue* q = dequeue(elem);
+ delete reinterpret_cast<route_head*>(q);
+ }
+ head_ct = 0;
+ waypt_ct = 0;
+}
+
+void
+RouteList::copy(RouteList** dst) const
+{
+ queue* elem, *tmp, *elem2, *tmp2;
+
+ if (*dst == nullptr) {
+ *dst = new RouteList;
+ }
+
+ const char RPT[] = "RPT";
+ QUEUE_FOR_EACH(&head, elem, tmp) {
+ auto rte_old = reinterpret_cast<route_head*>(elem);
+
+ route_head* rte_new = route_head_alloc();
+ rte_new->rte_name = rte_old->rte_name;
+ rte_new->rte_desc = rte_old->rte_desc;
+ rte_new->rte_urls = rte_old->rte_urls;
+ rte_new->fs = fs_chain_copy(rte_old->fs);
+ rte_new->rte_num = rte_old->rte_num;
+ (*dst)->add_head(rte_new);
+ QUEUE_FOR_EACH(&rte_old->waypoint_list, elem2, tmp2) {
+ (*dst)->add_wpt(rte_new, new Waypoint(*reinterpret_cast<Waypoint*>(elem2)), false, RPT, 3);
+ }
+ }
+}
+
+void
+RouteList::restore(RouteList* src)
+{
+ if (src == nullptr) {
+ return;
+ }
+
+ flush();
+ QUEUE_MOVE(&head, &src->head);
+
+ head_ct = src->head_ct;
+ src->head_ct = 0;
+ waypt_ct = src->waypt_ct;
+ src->waypt_ct = 0;
+}
+
+void RouteList::swap(RouteList& other)
+{
+ queue tmp_head;
+ QUEUE_MOVE(&tmp_head, &(other.head));
+ QUEUE_MOVE(&(other.head), &(this->head));
+ QUEUE_MOVE(&(this->head), &tmp_head);
+
+ const auto tmp_head_ct = other.head_ct;
+ other.head_ct = this->head_ct;
+ this->head_ct = tmp_head_ct;
+
+ const auto tmp_waypt_ct = other.waypt_ct;
+ other.waypt_ct = this->waypt_ct;
+ this->waypt_ct = tmp_waypt_ct;
+}
+
+void RouteList::sort(Compare cmp)
+{
+ sortqueue(&head, cmp);
+}
+
#include <QtCore/QString> // for QString
#include <cstdlib> // for abort
-extern queue my_route_head;
-extern queue my_track_head;
-
#if FILTERS_ENABLED
+#define MYNAME "sort"
template <class T>
inline int sgn(T v)
}
}
-int SortFilter::sort_comp_rh(const queue* a, const queue* b)
+int SortFilter::sort_comp_rh_by_description(const queue* a, const queue* b)
{
const route_head* x1 = reinterpret_cast<const route_head*>(a);
const route_head* x2 = reinterpret_cast<const route_head*>(b);
- switch (rh_sort_mode) {
- case SortModeRteHd::description:
- return x1->rte_desc.compare(x2->rte_desc);
- case SortModeRteHd::name:
- return x1->rte_name.compare(x2->rte_name);
- case SortModeRteHd::number:
- return cmp(x1->rte_num, x2->rte_num);
- default:
- abort();
- return 0; /* Internal caller error. */
- }
+ return x1->rte_desc.compare(x2->rte_desc);
}
-int SortFilter::SortCompWptFunctor::operator()(const queue* a, const queue* b)
+int SortFilter::sort_comp_rh_by_name(const queue* a, const queue* b)
{
- return that->sort_comp_wpt(a, b);
+ const route_head* x1 = reinterpret_cast<const route_head*>(a);
+ const route_head* x2 = reinterpret_cast<const route_head*>(b);
+
+ return x1->rte_name.compare(x2->rte_name);
}
-int SortFilter::SortCompRteHdFunctor::operator()(const queue* a, const queue* b)
+int SortFilter::sort_comp_rh_by_number(const queue* a, const queue* b)
{
- return that->sort_comp_rh(a, b);
+ const route_head* x1 = reinterpret_cast<const route_head*>(a);
+ const route_head* x2 = reinterpret_cast<const route_head*>(b);
+
+ return cmp(x1->rte_num, x2->rte_num);
+}
+
+int SortFilter::SortCompWptFunctor::operator()(const queue* a, const queue* b)
+{
+ return that->sort_comp_wpt(a, b);
}
void SortFilter::process()
{
SortCompWptFunctor sort_comp_wpt_f(*this);
- SortCompRteHdFunctor sort_comp_rh_f(*this);
if (wpt_sort_mode != SortModeWpt::none) {
sortqueue(&waypt_head, sort_comp_wpt_f);
}
if (rte_sort_mode != SortModeRteHd::none) {
- rh_sort_mode = rte_sort_mode;
- sortqueue(&my_route_head, sort_comp_rh_f);
+ switch (rte_sort_mode) {
+ case SortModeRteHd::description:
+ route_sort(SortFilter::sort_comp_rh_by_description);
+ break;
+ case SortModeRteHd::name:
+ route_sort(sort_comp_rh_by_name);
+ break;
+ case SortModeRteHd::number:
+ route_sort(sort_comp_rh_by_number);
+ break;
+ default:
+ fatal(MYNAME ": unknown route sort mode.");
+ }
}
if (trk_sort_mode != SortModeRteHd::none) {
- rh_sort_mode = trk_sort_mode;
- sortqueue(&my_track_head, sort_comp_rh_f);
+ switch (trk_sort_mode) {
+ case SortModeRteHd::description:
+ track_sort(sort_comp_rh_by_description);
+ break;
+ case SortModeRteHd::name:
+ track_sort(sort_comp_rh_by_name);
+ break;
+ case SortModeRteHd::number:
+ track_sort(sort_comp_rh_by_number);
+ break;
+ default:
+ fatal(MYNAME ": unknown track sort mode.");
+ }
}
}
SortModeRteHd rte_sort_mode = SortModeRteHd::none; /* How are we sorting these? */
SortModeRteHd trk_sort_mode = SortModeRteHd::none; /* How are we sorting these? */
- SortModeRteHd rh_sort_mode = SortModeRteHd::none;
char* opt_sm_gcid, *opt_sm_shortname, *opt_sm_description, *opt_sm_time;
char* opt_sm_rtenum, *opt_sm_rtename, *opt_sm_rtedesc;
};
int sort_comp_wpt(const queue* a, const queue* b);
- int sort_comp_rh(const queue* a, const queue* b);
+ static int sort_comp_rh_by_description(const queue* a, const queue* b);
+ static int sort_comp_rh_by_name(const queue* a, const queue* b);
+ static int sort_comp_rh_by_number(const queue* a, const queue* b);
class SortCompWptFunctor
{
SortFilter* that;
};
- class SortCompRteHdFunctor
- {
- public:
- explicit SortCompRteHdFunctor(SortFilter& obj) : that(&obj) {}
- int operator()(const queue* a, const queue* b);
-
- private:
- SortFilter* that;
- };
-
};
#endif // FILTERS_ENABLED
#endif // SORT_H_INCLUDED_
void StackFilter::process()
{
- struct stack_elt* tmp_elt = nullptr;
+ stack_elt* tmp_elt = nullptr;
queue* elem = nullptr;
queue* tmp = nullptr;
queue tmp_queue;
+ RouteList* route_list_ptr;
if (opt_push) {
- tmp_elt = (struct stack_elt*)xmalloc(sizeof(struct stack_elt));
+ tmp_elt = new stack_elt;
QUEUE_MOVE(&(tmp_elt->waypts), &waypt_head);
tmp_elt->waypt_ct = waypt_count();
}
}
- tmp = nullptr;
- route_backup(&(tmp_elt->route_count), &tmp);
- QUEUE_MOVE(&(tmp_elt->routes), tmp);
- xfree(tmp);
+ route_list_ptr = &(tmp_elt->routes);
+ route_backup(&route_list_ptr);
if (!opt_copy) {
route_flush_all_routes();
}
- tmp = nullptr;
- track_backup(&(tmp_elt->track_count), &tmp);
- QUEUE_MOVE(&(tmp_elt->tracks), tmp);
- xfree(tmp);
+ route_list_ptr = &(tmp_elt->tracks);
+ track_backup(&route_list_ptr);
if (!opt_copy) {
route_flush_all_tracks();
}
waypt_add(reinterpret_cast<Waypoint *>(elem));
}
route_append(&(stack->routes));
- route_flush(&(stack->routes));
+ stack->routes.flush();
track_append(&(stack->tracks));
- route_flush(&(stack->tracks));
+ stack->tracks.flush();
} else if (opt_discard) {
waypt_flush(&(stack->waypts));
- route_flush(&(stack->routes));
- route_flush(&(stack->tracks));
+ stack->routes.flush();
+ stack->tracks.flush();
} else {
waypt_flush(&waypt_head);
QUEUE_MOVE(&(waypt_head), &(stack->waypts));
}
stack = tmp_elt->next;
- xfree(tmp_elt);
+ delete tmp_elt;
} else if (opt_swap) {
tmp_elt = stack;
while (swapdepth > 1) {
QUEUE_MOVE(&tmp_queue, &(tmp_elt->waypts));
QUEUE_MOVE(&(tmp_elt->waypts), &waypt_head);
QUEUE_MOVE(&waypt_head, &tmp_queue);
-
- QUEUE_MOVE(&tmp_queue, &(tmp_elt->routes));
- tmp = nullptr;
- route_backup(&(tmp_elt->route_count), &tmp);
- QUEUE_MOVE(&(tmp_elt->routes), tmp);
- xfree(tmp);
- route_restore(&tmp_queue);
-
- QUEUE_MOVE(&tmp_queue, &(tmp_elt->tracks));
- tmp = nullptr;
- track_backup(&(tmp_elt->track_count), &tmp);
- QUEUE_MOVE(&(tmp_elt->tracks), tmp);
- xfree(tmp);
- track_restore(&tmp_queue);
-
unsigned int tmp_count = waypt_count();
set_waypt_count(tmp_elt->waypt_ct);
tmp_elt->waypt_ct = tmp_count;
+
+ route_swap(tmp_elt->routes);
+
+ track_swap(tmp_elt->tracks);
}
}
void StackFilter::exit()
{
- struct stack_elt* tmp_elt = nullptr;
+ stack_elt* tmp_elt = nullptr;
if (warnings_enabled && stack) {
warning(MYNAME " Warning: leftover stack entries; "
waypt_flush(&(stack->waypts));
tmp_elt = stack;
stack = stack->next;
- xfree(tmp_elt);
+ delete tmp_elt;
}
}
ARG_TERMINATOR
};
- struct stack_elt {
+ class stack_elt
+ {
+ public:
+ stack_elt()
+ {
+ QUEUE_INIT(&waypts);
+ }
+
queue waypts;
- queue routes;
- queue tracks;
- unsigned int waypt_ct;
- int route_count;
- int track_count;
- struct stack_elt* next;
- }* stack = nullptr;
+ RouteList routes;
+ RouteList tracks;
+ unsigned int waypt_ct{0};
+ stack_elt* next{nullptr};
+ };
+ stack_elt* stack = nullptr;
};
#endif // FILTERS_ENABLED
wpt = new Waypoint(*wpt);
switch (current_target) {
case 'R':
- route_add_wpt_named(rte, wpt, RPT, name_digits);
+ route_add_wpt(rte, wpt, RPT, name_digits);
break;
case 'T':
- track_add_wpt_named(rte, wpt, RPT, name_digits);
+ track_add_wpt(rte, wpt, RPT, name_digits);
break;
}
}
{
Waypoint* temp = new Waypoint(*wpt);
if (current_target == 'R') {
- route_add_wpt_named(current_rte, temp, current_namepart, name_digits);
+ route_add_wpt(current_rte, temp, current_namepart, name_digits);
} else if (current_target == 'T') {
- track_add_wpt_named(current_trk, temp, current_namepart, name_digits);
+ track_add_wpt(current_trk, temp, current_namepart, name_digits);
} else {
waypt_add(temp);
}